
module StrMap = Map.Make(String)
module StrSet = Set.Make(String)

exception Ident_found of string

let alphabetic = ["a";"b";"c";"d";"e";"f";"g";"h";"i";"j";"k";"l";
	"m";"n";"o";"p";"q";"r";"s";"t";"u";"v";"w";"x";"y";"z"]
	
let alphabetic_casefree = alphabetic @ (List.map String.uppercase alphabetic)

let alphanumeric = alphabetic_casefree @ ["0";"1";"2";"3";"4";"5";"6";"7";"8";"9"]

(* Start with StrMap.empty,StrSet.empty,StrSet.empty *)
let free_ident (map,dests,absolute) ident isVisible =
	if isVisible then
		((StrMap.add ident ident map), (StrSet.add ident dests), absolute)
	else
		let rec create_ident prefix alphabet depth =
			(if depth = 0 then
				(if not ((StrSet.mem prefix dests) 
					or (Hashtbl.mem Lexer.keywords prefix) 
					or (StrSet.mem prefix absolute)) then
					
					raise (Ident_found prefix))
			else
				List.iter (fun c ->
						create_ident (prefix ^ c) alphanumeric (depth - 1)) alphabet)
		in
		try
			let depth = ref 1 in
			while true do
				create_ident "" alphabetic_casefree !depth;
				incr depth
			done;
			(map,dests,absolute)
		with
			| Ident_found(s) -> ((StrMap.add ident s map),(StrSet.add s dests), absolute)
